home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / Mac OS X Throbber / Source / GDeviceUtils.cp < prev    next >
Text File  |  2000-06-23  |  12KB  |  483 lines

  1. /*------------------------------------------------------------------------------
  2. #
  3. #    GDeviceUtils.cp
  4. #
  5. #    by Eric Traut
  6. #
  7. ------------------------------------------------------------------------------*/
  8.  
  9. #include "GDeviceUtils.h"
  10.  
  11. #include <Memory.h>
  12. #include <LowMem.h>
  13. #include <Displays.h>
  14. #include <Traps.h>
  15.  
  16.  
  17.  
  18. /*---------------------------------------------------------------
  19.     GraphicSurface
  20. ---------------------------------------------------------------*/
  21.  
  22. GraphicSurface::GraphicSurface()
  23. {
  24.     // Nothing to do
  25.     mPixelData = NULL;
  26. }
  27.         
  28.  
  29. /*---------------------------------------------------------------
  30.     ExtractRealDeviceInfo
  31. ---------------------------------------------------------------*/
  32.  
  33. void
  34. GraphicSurface::ExtractRealDeviceInfo(
  35.     GDHandle            inGDevice)
  36. {
  37.     PixMapHandle        pixMap;
  38.     
  39.     pixMap = inGDevice[0]->gdPMap;
  40.     
  41.     mRowBytes = pixMap[0]->rowBytes & 0x3FFF;
  42.     mPixelData = (UInt8 *)pixMap[0]->baseAddr;
  43.     mBitDepth = pixMap[0]->pixelSize;
  44.     mHeight = pixMap[0]->bounds.bottom - pixMap[0]->bounds.top;
  45.     mWidth = pixMap[0]->bounds.right - pixMap[0]->bounds.left;
  46. }
  47.  
  48.  
  49. /*---------------------------------------------------------------
  50.     CapturedGDevice
  51. ---------------------------------------------------------------*/
  52.  
  53. CapturedGDevice::CapturedGDevice()
  54. {
  55.     mGDHandle = NULL;
  56.     mDeviceCaptured = false;
  57.  
  58.     mVirtualDeviceList = NULL;
  59.     mVirtualDeviceCount = 0;
  60.  
  61.     mBlendEffect = NULL;
  62. }
  63.         
  64.  
  65. /*---------------------------------------------------------------
  66.     ~CapturedGDevice
  67. ---------------------------------------------------------------*/
  68.  
  69. CapturedGDevice::~CapturedGDevice()
  70. {
  71.     if (mDeviceCaptured)
  72.         UncaptureDevice();
  73. }
  74.         
  75.  
  76. /*---------------------------------------------------------------
  77.     CaptureDevice
  78. ---------------------------------------------------------------*/
  79.  
  80. void
  81. CapturedGDevice::CaptureDevice(
  82.     GDHandle            inGDevice,
  83.     VirtualGDevice **    inVDeviceList,
  84.     UInt32                inVDeviceCount)
  85. {
  86.     HideCursor();
  87.     if (mDeviceCaptured)
  88.         UncaptureDevice();
  89.  
  90.     mGDHandle = inGDevice;
  91.     
  92.     OSErr err = ::DMGetDisplayIDByGDevice(inGDevice, &mDisplayID, false);
  93.     if (err != noErr)
  94.         DebugStr("\pCouldn't get DisplayID");
  95.     
  96.     mCapturedSurface.ExtractRealDeviceInfo(mGDHandle);
  97.  
  98.     // For now, we only support 16-bit mode.
  99.     if (mCapturedSurface.GetBitDepth() != 16)
  100.     {
  101.         // fix me - report an error
  102.     }
  103.     else
  104.     {
  105.         mVirtualDeviceList = inVDeviceList;
  106.         mVirtualDeviceCount = inVDeviceCount;
  107.  
  108.         // Tell each of the virtual monitors to initialize
  109.         // itself. Initialize in reverse order because
  110.         // the display manager orders them that way.
  111.         for (SInt32 vDeviceIndex = inVDeviceCount - 1; vDeviceIndex >= 0; vDeviceIndex--)
  112.             inVDeviceList[vDeviceIndex]->Initialize(*this, vDeviceIndex);
  113.  
  114.         err = ::DMSetMainDisplay(inVDeviceList[0]->GetGDHandle(), NULL);
  115.         if (err != noErr)
  116.             DebugStr("\p Error SetMainDisplay");
  117.         RecomputeGDHandle();
  118.  
  119.         // We need to recompute the GDHandles from the display IDs
  120.         // because they may have been rearranged.
  121.         for (UInt32 vDeviceIndex = 0; vDeviceIndex < inVDeviceCount; vDeviceIndex++)
  122.             inVDeviceList[vDeviceIndex]->RecomputeGDHandle();
  123.  
  124.         // Now position the displays (Can't move main display)
  125.         for (SInt32 vDeviceIndex = 1; vDeviceIndex < inVDeviceCount; vDeviceIndex++)
  126.         {
  127.             Rect newPos;
  128.             inVDeviceList[vDeviceIndex]->GetPreferredPosition(newPos);
  129.             err = ::DMMoveDisplay(inVDeviceList[vDeviceIndex]->GetGDHandle(), newPos.left, newPos.top, NULL);
  130.             if (err != noErr)
  131.                 DebugStr("\pMoveDisplay failed");
  132.         }
  133.  
  134.         // Now get rid of the rounded area in the corners
  135.         RgnHandle    rgn = NewRgn();
  136.         RgnHandle    grayRgn = LMGetGrayRgn();
  137.         for (SInt32 vDeviceIndex = 0; vDeviceIndex < inVDeviceCount; vDeviceIndex++) {
  138.             GDHandle gdHandle = inVDeviceList[vDeviceIndex]->GetGDHandle();
  139.             SetDeviceAttribute(gdHandle, roundedDevice, false);
  140.  
  141.             Rect    r = (**gdHandle).gdRect;
  142.             if (r.left == 0 && r.top == 0) r.top = GetMBarHeight();
  143.             RectRgn(rgn, &r);
  144.             MacUnionRgn(grayRgn, rgn, grayRgn);
  145.         }
  146.         DisposeRgn(rgn);
  147.  
  148.         CWindowRecord wr;
  149.         CWindowPtr wp = (CWindowPtr)NewCWindow(&wr, &(**LMGetGrayRgn()).rgnBBox, "\p ", true, plainDBox, 0, false, 237);
  150.         CloseWindow((WindowPtr)wp);
  151.         
  152.         mDeviceCaptured = true;
  153.     }
  154.     ShowCursor();
  155. }
  156.  
  157.  
  158. /*---------------------------------------------------------------
  159.     UncaptureDevice
  160. ---------------------------------------------------------------*/
  161.  
  162. void
  163. CapturedGDevice::UncaptureDevice()
  164. {
  165.     if (mDeviceCaptured)
  166.     {
  167.         RecomputeGDHandle();
  168.         OSErr err = ::DMSetMainDisplay(mGDHandle, NULL);
  169.         if (err != noErr)
  170.             DebugStr("\p Error SetMainDisplay");
  171.         RecomputeGDHandle();
  172.  
  173.         // Tell each of the virtual monitors to 
  174.         // uninitialize itself.
  175.         for (UInt32 vDeviceIndex = 0; vDeviceIndex < mVirtualDeviceCount; vDeviceIndex++)
  176.         {
  177.             if (mVirtualDeviceList[vDeviceIndex] != NULL)
  178.                 mVirtualDeviceList[vDeviceIndex]->Uninitialize();
  179.         }
  180.  
  181.         mDeviceCaptured = false;
  182.     }
  183. }
  184.         
  185.  
  186. /*---------------------------------------------------------------
  187.     UncaptureDevice
  188. ---------------------------------------------------------------*/
  189.  
  190. void
  191. CapturedGDevice::SetPixelBase(
  192.     UInt8 *                inPixelBase)
  193. {
  194.     PixMapHandle        pixMap;
  195.     
  196.     RecomputeGDHandle();
  197.     if (mGDHandle != NULL)
  198.     {
  199.         pixMap = mGDHandle[0]->gdPMap;
  200.         pixMap[0]->baseAddr = (Ptr)inPixelBase;
  201.     }
  202. }
  203.  
  204.  
  205. /*---------------------------------------------------------------
  206.     UpdateCapturedScreen
  207. ---------------------------------------------------------------*/
  208.  
  209. void
  210. CapturedGDevice::UpdateCapturedScreen()
  211. {
  212.     if (mBlendEffect != NULL)
  213.     {
  214.         mBlendEffect->BlendVirtualDevices(
  215.                 mCapturedSurface, 
  216.                 mVirtualDeviceList,
  217.                 mVirtualDeviceCount);
  218.     }
  219. }
  220.  
  221.  
  222. /*---------------------------------------------------------------
  223.     RecomputeGDHandle
  224. ---------------------------------------------------------------*/
  225.  
  226. void
  227. CapturedGDevice::RecomputeGDHandle()
  228. {
  229.     OSErr        err;
  230.  
  231.     err = ::DMGetGDeviceByDisplayID(mDisplayID, &mGDHandle, false);
  232.     
  233.     if (err != noErr)
  234.     {
  235.         DebugStr("\pFailedToFindDevice");
  236.         mGDHandle = NULL;
  237.     }
  238. }
  239.  
  240.  
  241. /*---------------------------------------------------------------
  242.     SetGraphicBlendEffect
  243. ---------------------------------------------------------------*/
  244.  
  245. void
  246. CapturedGDevice::SetGraphicBlendEffect(
  247.     GraphicBlendEffect *    inBlendEffect)
  248. {
  249.     if (mBlendEffect != NULL)
  250.     {
  251.         GraphicBlendEffect *        tempEffect = mBlendEffect;
  252.         
  253.         // Set it to NULL first so time manager
  254.         // task doesn't call the effect after it's 
  255.         // deallocated.
  256.         mBlendEffect = NULL;
  257.         delete tempEffect;
  258.     }
  259.  
  260.     // We need to wipe the dest screen to black
  261.     ClearCapturedScreen();
  262.     
  263.     mBlendEffect = inBlendEffect;
  264. }
  265.  
  266.  
  267. /*---------------------------------------------------------------
  268.     SetGraphicBlendValue
  269. ---------------------------------------------------------------*/
  270.  
  271. void
  272. CapturedGDevice::SetGraphicBlendValue(
  273.     UInt32                    inValueIndex,
  274.     double                    inValue)
  275. {
  276.     if (mBlendEffect != NULL)
  277.     {
  278.         mBlendEffect->SetEffectValue(inValueIndex, inValue);
  279.     }
  280. }
  281.  
  282.  
  283. /*---------------------------------------------------------------
  284.     ClearCapturedScreen
  285. ---------------------------------------------------------------*/
  286.  
  287. void
  288. CapturedGDevice::ClearCapturedScreen()
  289. {
  290.     // The simple blend effect simply involves
  291.     // copying the pixels from the first virtual
  292.     // device to the destination surface.
  293.     UInt32                 totalRows = mCapturedSurface.GetHeight();
  294.     UInt32                 totalCols = mCapturedSurface.GetWidth();
  295.     UInt8 *             destPtr;
  296.     
  297.     for (UInt32 row = 0; row < totalRows; row++)
  298.     {
  299.         destPtr = mCapturedSurface.GetPixelDataPtr() + mCapturedSurface.GetRowBytes() * row;
  300.         
  301.         for (UInt32 col = 0; col < totalCols; col++)
  302.         {
  303.             *(UInt16 *)destPtr = 0;
  304.             destPtr += 2;
  305.         }
  306.     }
  307. }
  308.  
  309.  
  310. /*---------------------------------------------------------------
  311.     VirtualGDevice
  312. ---------------------------------------------------------------*/
  313.  
  314. VirtualGDevice::VirtualGDevice()
  315. {
  316.     mDeviceBacking = NULL;
  317.     mGDHandle = NULL;
  318.     mAddedToDeviceList = false;
  319. }
  320.  
  321.  
  322. /*---------------------------------------------------------------
  323.     ~VirtualGDevice
  324. ---------------------------------------------------------------*/
  325.  
  326. VirtualGDevice::~VirtualGDevice()
  327. {
  328.     Uninitialize();
  329. }
  330.  
  331.  
  332. /*---------------------------------------------------------------
  333.     Initialize
  334. ---------------------------------------------------------------*/
  335.  
  336. Boolean
  337. VirtualGDevice::Initialize(
  338.     CapturedGDevice &        inRealGDevice,
  339.     UInt32                    inIndex)
  340. {
  341.     // Allocate backing memory for the virtual device
  342.     Ptr backingPtr;
  343.     backingPtr = ::NewPtrClear(inRealGDevice.GetGraphicSurface().GetBackingSize());
  344.     
  345.     if (backingPtr == NULL)
  346.         return false;
  347.     
  348.     mDeviceBacking = backingPtr;
  349.     
  350.     // Allocate a new GDevice if this isn't the primary
  351.     // virtual device.
  352.     
  353.     // fix me - what is the first parameter?
  354.     mGDHandle = ::NewGDevice(0, -1);
  355.     if (mGDHandle == NULL)
  356.         return false;
  357.     ::HLock((Handle)mGDHandle);
  358.  
  359.     Handle itableHandle;
  360.     
  361.     itableHandle = ::NewHandle(0);
  362.     if (itableHandle == NULL)
  363.         return false;
  364.     
  365.     // Make a default inverse table
  366.     ::MakeITable(NULL, (ITabHandle)itableHandle, 4);
  367.     
  368.     mGDHandle[0]->gdRefNum = 0;
  369.     mGDHandle[0]->gdID = 1024 + inIndex;
  370.     mGDHandle[0]->gdType = 2;
  371.     mGDHandle[0]->gdITable = (ITabHandle)itableHandle;
  372.     mGDHandle[0]->gdFlags = (1L << gdDevType) |            // Color device
  373.                             (1L << noDriver) |            // No driver
  374.                             (1L << screenDevice) |        // It's a screen device (not printer)
  375.                             (1L << screenActive) |        // It's active
  376.                             (1L << burstDevice) |
  377.                             (1L << allInit);
  378.     mGDHandle[0]->gdMode = 129;
  379.  
  380.     // Set up the device rectangle
  381.     mGDHandle[0]->gdRect.left = (inIndex % 2) * inRealGDevice.GetGraphicSurface().GetWidth();
  382.     mGDHandle[0]->gdRect.top = (inIndex / 2) * inRealGDevice.GetGraphicSurface().GetHeight();
  383.     mGDHandle[0]->gdRect.right = mGDHandle[0]->gdRect.left + inRealGDevice.GetGraphicSurface().GetWidth();
  384.     mGDHandle[0]->gdRect.bottom = mGDHandle[0]->gdRect.top + inRealGDevice.GetGraphicSurface().GetHeight();
  385.  
  386.     mPreferredPos = mGDHandle[0]->gdRect;
  387.     
  388.     // Now, set up the pix map for the gdevice
  389.     PixMapHandle        realPixMap = inRealGDevice.GetPixMapHandle();
  390.     PixMapHandle        virtPixMap = mGDHandle[0]->gdPMap;
  391.  
  392.     // Copy the pix map info 
  393.     virtPixMap[0]->baseAddr = mDeviceBacking;
  394.     virtPixMap[0]->rowBytes = realPixMap[0]->rowBytes;
  395.     virtPixMap[0]->bounds = realPixMap[0]->bounds;
  396.     virtPixMap[0]->pmVersion = realPixMap[0]->pmVersion;
  397.     virtPixMap[0]->packType = realPixMap[0]->packType;
  398.     virtPixMap[0]->packSize = realPixMap[0]->packSize;
  399.     virtPixMap[0]->hRes = realPixMap[0]->hRes;
  400.     virtPixMap[0]->vRes = realPixMap[0]->vRes;
  401.     virtPixMap[0]->pixelType = realPixMap[0]->pixelType;
  402.     virtPixMap[0]->pixelSize = realPixMap[0]->pixelSize;
  403.     virtPixMap[0]->cmpCount = realPixMap[0]->cmpCount;
  404.     virtPixMap[0]->cmpSize = realPixMap[0]->cmpSize;
  405.     virtPixMap[0]->planeBytes = realPixMap[0]->planeBytes;
  406.     virtPixMap[0]->pmReserved = realPixMap[0]->pmReserved;
  407.  
  408.     if (virtPixMap[0]->pmTable != NULL)
  409.         virtPixMap[0]->pmTable[0]->ctFlags = 0x8000;
  410.  
  411.     DMAddDisplay(
  412.             mGDHandle, 
  413.             mGDHandle[0]->gdRefNum, 
  414.             mGDHandle[0]->gdMode, 
  415.             0, 
  416.             0, 
  417.             NULL, 
  418.             NULL);
  419.  
  420.     DMEnableDisplay(mGDHandle, NULL);
  421.  
  422.     OSErr err = ::DMGetDisplayIDByGDevice(mGDHandle, &mDisplayID, false);
  423.     if (err != noErr)
  424.         DebugStr("\pCouldn't get DisplayID");
  425.  
  426.     mAddedToDeviceList = true;
  427.  
  428.     mVirtualSurface.ExtractRealDeviceInfo(mGDHandle);
  429.  
  430.     return true;
  431. }
  432.  
  433.  
  434. /*---------------------------------------------------------------
  435.     Uninitialize
  436. ---------------------------------------------------------------*/
  437.  
  438. void
  439. VirtualGDevice::Uninitialize()
  440. {
  441.     if (mDeviceBacking != NULL)
  442.     {
  443.         if (mAddedToDeviceList)
  444.         {
  445.             RecomputeGDHandle();
  446.             ::DMRemoveDisplay(mGDHandle, NULL);            
  447.             mAddedToDeviceList = false;
  448.         }
  449.  
  450.         if (mGDHandle != NULL)
  451.             ::DisposeGDevice(mGDHandle);
  452.         mGDHandle = NULL;
  453.  
  454.         ::DisposePtr(mDeviceBacking);
  455.         mDeviceBacking = NULL;
  456.     }
  457. }
  458.  
  459.  
  460. /*---------------------------------------------------------------
  461.     RecomputeGDHandle
  462. ---------------------------------------------------------------*/
  463.  
  464. void
  465. VirtualGDevice::RecomputeGDHandle()
  466. {
  467.     OSErr        err;
  468.  
  469.     err = ::DMGetGDeviceByDisplayID(mDisplayID, &mGDHandle, false);
  470.  
  471.     if (err != noErr)
  472.     {
  473.         DebugStr("\pFailedToFindDevice");
  474.         mGDHandle = NULL;
  475.     }
  476.     else
  477.     {
  478.         // Reset the backing address. It seems
  479.         // to get reset when we set the main device.
  480.         mGDHandle[0]->gdPMap[0]->baseAddr = mDeviceBacking;
  481.     }
  482. }
  483.